package com.si.anddos.library.main;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;

import android.os.Environment;
import android.text.format.Time;
import android.util.Log;

import com.si.anddos.DownloadProviderService;
import com.si.anddos.R;
import com.si.anddos.dpadapters.AnddosDbAdapter;
import com.si.anddos.dpadapters.DatabaseProvider;
import com.si.anddos.dpadapters.Download;
import com.si.anddos.dpadapters.DownloadTime;
import com.si.anddos.library.main.factory.ServiceProviderFactory;
import com.si.anddos.library.provider.FileInfo;
import com.si.anddos.library.provider.ProviderMessage;
import com.si.anddos.library.provider.ServiceProvider;
import com.si.anddos.library.provider.ServiceProviderException;
import com.si.anddos.utils.FileSaver;

/**
 * 
 * @author Carlos Martinez
 * 
 */
public class DownloadProviderThread extends Thread {

	private LinkedList<DownloadTime> downloads;
	private DatabaseProvider dbProvider;
	private DownloadProviderService mps;
	private static boolean started = false;
	private static ServiceProvider activeServiceProvider;
	private static Download runningDownload;

	public boolean hasStarted() {
		return started;
	}

	public DownloadProviderThread(DownloadProviderService service) {
		this.dbProvider = new DatabaseProvider(service.getApplicationContext());
		this.mps = service;
		started = true;
	}

	/**
	 * This function process all downloads in queue
	 */
	private void downloadFiles() {
		this.dbProvider.open();
		for (DownloadTime downloadTime : this.downloads) {
			boolean error = false;
			// returns download for time
			Download d = this.dbProvider.getDownload(downloadTime.getId());

			// get current time
			Time curTime = new Time();
			curTime.setToNow();

			// prepare provider message
			ProviderMessage pm = new ProviderMessage(this.mps.getText(
					R.string.downloadServiceFinished).toString()
					+ " " + d.getFileName(), this.mps);

			if (d.getDateTime().before(curTime)) {
				try {
					runningDownload = d;
					// update status and get provider for downloading
					this.dbProvider.updateStatusDownload(d.getId(),
							AnddosDbAdapter.StatusProcessing);
					activeServiceProvider = ServiceProviderFactory
							.getProvider(new URL(d.getUrl()));

					AccountDetail ad = activeServiceProvider.getAccountDetail(d
							.getAccount());

					FileInfo tmp = activeServiceProvider.getFileInfo();
					if (activeServiceProvider != null && tmp != null) {
						// get file saver for download
						File destinationDir = new File(Environment.
								getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
								.toString());
						destinationDir.mkdirs();
						
						File destinationFile = new File(destinationDir.toString(), tmp.getName());
						destinationFile.delete();
						
						//prepare file saver and start download
						FileSaver fs = new FileSaver(destinationFile);
						activeServiceProvider.setFileSaver(fs);
						if (ad.isBilled()) {
							activeServiceProvider.download(d.getAccount(),
									fs.getPosition());
						} else {
							activeServiceProvider.download(fs.getPosition());
						}

						if (fs.getPosition() == tmp.getSize()) {
							// update database
							this.dbProvider.updateStatusDownload(d.getId(),
									AnddosDbAdapter.StatusDone);

							// send notification to notification bar
							this.mps.showNotification(d.getId(),
									R.string.downloadServiceFinished,
									d.getFileName());
						} else {
							// update database
							this.dbProvider.updateStatusDownload(d.getId(),
									AnddosDbAdapter.StatusStopped);

							pm.setMessage(this.mps.getText(
									R.string.downloadServiceStoppedFile)
									.toString()
									+ " " + d.getFileName());
						}
					}
				} catch (MalformedURLException e) {
					Log.i("MainProviderService", "Exeption in url");
					pm.setMessage(this.mps.getText(
							R.string.downloadServiceError).toString()
							+ " " + d.getFileName());
					this.dbProvider.updateStatusDownload(d.getId(),
							AnddosDbAdapter.StatusError);
					error = true;
				} catch (FileNotFoundException e) {
					Log.i("Saving error", "file not found");
					e.printStackTrace();
					pm.setMessage(this.mps.getText(
							R.string.downloadServiceError).toString()
							+ " " + d.getFileName());
					this.dbProvider.updateStatusDownload(d.getId(),
							AnddosDbAdapter.StatusError);
					error = true;
				} catch (ServiceProviderException e) {
					Log.i("File download error",
							"file could not be downloaded for some reason-service");
					pm.setMessage(e.getMessage() + " " + d.getFileName());
					e.printStackTrace();
					this.dbProvider.updateStatusDownload(d.getId(),
							AnddosDbAdapter.StatusError);
					error = true;
				} catch (IOException e) {
					Log.i("File download error",
							"file could not be downloaded for some reason-IO");
					pm.setMessage(this.mps.getText(
							R.string.downloadServiceError).toString()
							+ " " + d.getFileName());
					this.dbProvider.updateStatusDownload(d.getId(),
							AnddosDbAdapter.StatusError);
					error = true;
				} finally {
					pm.showMessage();
					if (error) {
						// send notification to notification bar
						this.mps.showNotification(d.getId(),
								R.string.downloadServiceError, d.getFileName());
					}
				}
			}
		}
		this.dbProvider.close();

		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		this.reloadDownload();
	}

	public static void setStarted(boolean s) {
		started = s;
	}

	private void reloadDownload() {
		this.dbProvider.open();
		this.downloads = this.dbProvider.getDownloadsTimes();
		this.dbProvider.close();

		if (this.downloads.isEmpty()) {
			this.mps.stopSelf();
		} else {
			this.downloadFiles();
		}
	}

	@Override
	public void run() {
		// Looper.prepare();
		while (started) {
			this.reloadDownload();
		}
		// Looper.loop();
	}

	public static ServiceProvider getActiveProvider() {
		return activeServiceProvider;
	}

	public static void stopDownload(long downloadId) {
		if (runningDownload != null && runningDownload.getId() == downloadId) {
			activeServiceProvider.stopDownload();
		} else {
			System.out.println("Nothing to stop");
		}
	}
}
